package com.cash.channel.web.logic;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cash.channel.api.constant.Constant;
import com.cash.channel.api.exception.CashChannelException;
import com.cash.channel.api.model.channel.ChannelModel;
import com.cash.channel.api.model.callback.*;
import com.cash.channel.api.service.ApiService;
import com.cash.channel.api.service.ChannelService;
import com.cash.channel.web.model.RequestModel;
import com.cash.channel.web.signature.AESTool;
import com.cash.channel.web.signature.RSATool;
import com.cash.channel.web.signature.SignatureTool;
import com.cash.channel.web.utils.HttpRequestUtils;
import com.cash.common.model.CodeEnum;
import com.cash.common.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.Base64;

@Slf4j
@Service
public class CallBackLogic {

    @Autowired
    private ChannelService channelService;

    @Autowired
    private ApiService cashChannelApiService;

    public JSON commonBindCardCallBack(String channel, BankCardCallBack callBack) throws CashChannelException {
        return commonCallbackPush(channel, callBack, Constant.CALLBALL_URL_TYPE.BIND_CARD_CALLBACK);
    }

    public JSON commonDeductCallBack(String channel, RepayStatusCallBack callBack) throws CashChannelException {
        return commonCallbackPush(channel, callBack, Constant.CALLBALL_URL_TYPE.DEDUCT_CALLBACK);
    }

    public JSON commonQcOrderStatusCallBack(String channel, ApplyAuditStatusCallBack callBack) throws CashChannelException {
        return commonCallbackPush(channel, callBack, Constant.CALLBALL_URL_TYPE.QC_ORDER_STATUS_CALLBACK);
    }

    public JSON commonRepayPlanSynCallBack(String channel, RepayPlanListCallBack callBack) throws CashChannelException {
        return commonCallbackPush(channel, callBack, Constant.CALLBALL_URL_TYPE.REPAY_PLAN_SYN_CALLBACK);
    }

    public JSON commonWdOrderStatusCallBack(String channel, LoanStatusCallBack callBack) throws CashChannelException {
        return commonCallbackPush(channel, callBack, Constant.CALLBALL_URL_TYPE.WD_ORDER_STATUS_CALLBACK);
    }

    private JSONObject commonCallbackPush(String channel, Object callbackObject, String callbackType) throws CashChannelException {
        String url = channelService.getChannelCallbackUrl(channel, callbackType);
        JSON callbackJson = createCallbackJson(channel, callbackObject);
        return HttpRequestUtils.httpPost(url, callbackJson);
    }

    private JSON createCallbackJson(String channel, Object callbackObject) throws CashChannelException {
        try {
            Result<ChannelModel> channelModelResult = cashChannelApiService.getChannelInfoByCode(channel);
            if (CodeEnum.ERROR.getCode().equals(channelModelResult.getCode())) {
                log.error("查询渠道["+channel+"]信息失败："+channelModelResult.getMsg());
                throw new CashChannelException("查询渠道["+channel+"]信息失败");
            }
            ChannelModel channelModel = channelModelResult.getData();
            RequestModel callbackParams = new RequestModel();
            callbackParams.setChannel(channel);
            callbackParams.setEncryptKey(Base64.getEncoder().encodeToString(RSATool.rsaEncryptByPrivateKey(RSATool.parseRSAPrivateKey(channelModel.getcPlatformPrivateKey()),
                    channelModel.getcPlatformAesKey().getBytes(StandardCharsets.UTF_8))));
            callbackParams.setEncrypt(1);
            callbackParams.setCompress(0);
            callbackParams.setData(Base64.getEncoder().encodeToString(AESTool.aesEncrypt(JSON.toJSONString(callbackObject).getBytes(StandardCharsets.UTF_8), channelModel.getcPlatformAesKey())));
            callbackParams.setSign(Base64.getEncoder().encodeToString(RSATool.rsaSignByPrivateKey(RSATool.parseRSAPrivateKey(channelModel.getcPlatformPrivateKey()),
                    SignatureTool.buildSignContent(callbackParams).getBytes(StandardCharsets.UTF_8))));
            return (JSON) JSON.toJSON(callbackParams);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new CashChannelException("加密调用数据失败["+e.getMessage()+"]");
        }
    }

}
